# encoding: utf-8
"""
@author:Daniel
@license: Apache Licence
@file: api_builder_generater.py
@time: 2020/07/17
@contact: tongdangdang1@yy.com
"""
import os
import re
import sys
from datetime import datetime
from string import Template


class ApiBuilderGenerator(object):
    @classmethod
    def generate(cls, api_name, param_list, param_type_list, module_target_path, sdk_version, package_name=None):
        lines = []
        api_name_list = list(api_name)
        api_name_list[0] = api_name_list[0].upper()
        api_class_name = "".join(api_name_list)

        # module name使用小写的下划线
        api_module_name_list = list(map(lambda x: x.lower(), re.findall('[A-Z][^A-Z]*', api_class_name)))
        api_module_name = "_".join(api_module_name_list)

        template_file = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'api_builder.template'), 'r')
        tmpl = Template(template_file.read())

        methods = []
        param_method_tmpl = Template('''    @parameter(${ORDER}, "${TYPE}")\n    def ${PARAM_NAME}(self, \
${PARAM_NAME}):\n        return self\n\n''')
        order = 1
        for param_name in param_list:
            methods.append(param_method_tmpl.substitute(
                ORDER=order,
                TYPE=param_type_list[order - 1],
                PARAM_NAME=param_name
            ))
            order += 1
        param_call_list = list(map(lambda x: "{}({})".format(x, x), param_list))
        param_call = '.'.join(param_call_list)
        param_call = param_call if not param_call else "." + param_call
        methods_call_tmpl = Template('''def ${API_NAME}(${PARAMs}):\n    api_cmd = ${API_CLASS_NAME}ApiBuilder()\
${PARAM_CALL}.build()\n    send_command(api_cmd)
''')
        method_call = methods_call_tmpl.substitute(
            API_NAME=api_name,
            API_CLASS_NAME=api_class_name,
            PARAMs=", ".join(param_list),
            PARAM_CALL=param_call
        )

        lines.append(tmpl.substitute(
            API_NAME=package_name + "." + api_name if package_name else api_name,
            API_MODULE_NAME=api_module_name,
            API_CLASS_NAME=api_class_name,
            DATE=datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            SDK_VERSION=sdk_version,
            METHODS="".join(methods),
            METHOD_CALL=method_call
        ))
        file_path = module_target_path + '/{0}'.format(api_module_name + "_builder.py")
        class_file = open(file_path, 'w')
        class_file.writelines(lines)
        class_file.close()

    @classmethod
    def generate_module(cls, api_name, param_list, param_type_list, package_name=None):
        lines = []
        api_name_list = list(api_name)
        api_name_list[0] = api_name_list[0].upper()
        api_class_name = "".join(api_name_list)

        template_file = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'api_module_builder.template'), 'r')
        tmpl = Template(template_file.read())
        methods = []
        param_method_tmpl = Template('''    @parameter(${ORDER}, "${TYPE}")\n    def ${PARAM_NAME}(self, \
${PARAM_NAME}):\n        return self\n\n''')
        order = 1
        for param_name in param_list:
            methods.append(param_method_tmpl.substitute(
                ORDER=order,
                TYPE=param_type_list[order - 1],
                PARAM_NAME=param_name
            ))
            order += 1
        param_call_list = list(map(lambda x: "{}({})".format(x, x), param_list))
        param_call = '.'.join(param_call_list)
        param_call = param_call if not param_call else "." + param_call
        if param_list:
            methods_call_tmpl = Template('''def ${API_NAME}(self, ${PARAMs}):\n    api_cmd = ${API_CLASS_NAME}ApiBuilder()\
${PARAM_CALL}.build()\n    self.driver.send_command(api_cmd)
    ''')
        else:
            methods_call_tmpl = Template('''def ${API_NAME}(self${PARAMs}):\n    api_cmd = ${API_CLASS_NAME}ApiBuilder()\
${PARAM_CALL}.build()\n    self.driver.send_command(api_cmd)
                ''')
        method_call = methods_call_tmpl.substitute(
            API_NAME=api_name,
            API_CLASS_NAME=api_class_name,
            PARAMs=", ".join(param_list),
            PARAM_CALL=param_call
        )

        lines.append(tmpl.substitute(
            API_NAME=package_name + "." + api_name if package_name else api_name,
            API_CLASS_NAME=api_class_name,
            METHODS="".join(methods),
            METHOD_CALL=method_call
        ))
        return lines


def _build_java_apis_from_java_file(java_file, dir_path, sdk_version, package_name):
    """从本地Java文件生成api builder类"""
    with open(java_file, 'r') as file_obj:
        for line in file_obj:
            regex = r'\s*public\s+\w+\s+(\w+)\((.*)\)'
            match_obj = re.match(regex, line)
            if match_obj:
                api_name = match_obj.group(1)
                param_str = match_obj.group(2)

                param_arr = param_str.split(',')
                param_name_list = []
                param_type_list = []
                for param in param_arr:
                    if not param:
                        continue
                    k_v = param.strip().split(' ')
                    param_type_list.append(k_v[0].strip())
                    param_name_list.append(k_v[1].strip())

                print("param_type:{}, param_name:{}".format(param_type_list, param_name_list))
                ApiBuilderGenerator.generate(api_name, param_name_list, param_type_list, dir_path, sdk_version,
                                             package_name)


def _kotlin_basic_type_to_java_basic_type(param_type):
    kotlin_type = param_type.replace("Int", "int").replace("Long", "long") \
        .replace("Boolean", "boolean").replace("?", "").replace(":", "")
    return kotlin_type


def _build_kotlin_apis_from_kotlin_file(kotlin_file, dir_path, sdk_version, package_name):
    """从本地kotlin文件生成 api builder类"""
    with open(kotlin_file, 'r', encoding='UTF-8') as file_obj:
        for line in file_obj:
            # fun startPreview(viewGroup: ViewGroup?)
            # regex = '\s*fun\s+\w+\s+(\w+)'
            regex = r'\s*fun\s+(\w+)\((.*)\)'
            match_obj = re.match(regex, line)
            if match_obj:
                # print(match_obj)
                api_name = match_obj.group(1)
                param_str = match_obj.group(2)
                param_arr = param_str.split(',')
                param_name_list = []
                param_type_list = []
                for param in param_arr:
                    if not param:
                        continue
                    k_v = param.strip().split(' ')
                    param_type_list.append(_kotlin_basic_type_to_java_basic_type(k_v[1]).strip())
                    param_name_list.append(_kotlin_basic_type_to_java_basic_type(k_v[0]).strip())
                print("api_name:{}".format(api_name))
                print("param_type:{}, param_name:{}".format(param_type_list, param_name_list))
                ApiBuilderGenerator.generate(api_name, param_name_list, param_type_list, dir_path, sdk_version,
                                             package_name)

def _build_java_apis_from_file(file_path, dir_path, sdk_version, package_name):
    file_type = ''
    regexs = {
        'java': r'\s*public\s+\w+\s+(\w+)\((.*)\)',
        'kotlin': r'\s*fun\s+(\w+)\((.*)\)'
    }
    if file_path.endswith('.java'):
        file_type = 'java'
    elif file_path.endswith('.kt'):
        file_type = 'kotlin'
    api_module_name = file_path.replace(os.sep, '/').split('/')[-1].replace('.kt', '').replace('.java', '')
    with open(file_path, 'r', encoding='UTF-8') as file_obj:
        file_path = dir_path + '/{0}'.format(api_module_name + "_builder.py")
        class_file = open(file_path, 'w')
        head_tmpl = Template('''# encoding: utf-8\n"""\n@sdk version: ${SDK_VERSION}\n@author:auto generate code\n\
@license: Apache Licence\n@time: ${DATE}\n@contact: zhouyusheng1@yy.com\n"""\n\
from sdktest_module.utils.api_base_builder import ApiBaseBuilder, parameter\n''')
        class_file.writelines(list(head_tmpl.substitute(SDK_VERSION=sdk_version, DATE=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
        for line in file_obj:
            regex = regexs[file_type]
            match_obj = re.match(regex, line)
            if match_obj:
                # print(match_obj)
                api_name = match_obj.group(1)
                param_str = match_obj.group(2)
                param_arr = param_str.split(',')
                param_name_list = []
                param_type_list = []
                for param in param_arr:
                    if not param:
                        continue
                    k_v = param.strip().split(' ')
                    print("api_name:{}".format(api_name))
                    print(k_v)
                    param_type_list.append(k_v[0].strip() if file_type == 'java'
                                           else _kotlin_basic_type_to_java_basic_type(k_v[1]).strip())
                    param_name_list.append(k_v[1].strip() if file_type == 'java'
                                           else _kotlin_basic_type_to_java_basic_type(k_v[0]).strip())
                print("param_type:{}, param_name:{}".format(param_type_list, param_name_list))
                lines = ApiBuilderGenerator.generate_module(api_name, param_name_list, param_type_list, package_name)
                class_file.writelines(lines)
        class_file.close()


if __name__ == '__main__':
    # ApiBuilderGenerator.generate('demo', ["uid", "mode"], ["int", "string"], "./")
    # ApiBuilderGenerator.generate('demonoparam', [], [], "./")
    # setVideoEncoderConfig(ThunderVideoEncoderConfiguration yyVideoConfig)
    # {'api': 'setVideoEncoderConfig', 'param_name': ['yyVideoConfig'], 'param_type': ['ThunderVideoEncoderConfiguration'], 'param_value': [[1, 2]]}

    # ApiBuilderGenerator.generate('setVideoEncoderConfig', ["yyVideoConfig"], ["ThunderVideoEncoderConfiguration"], "../../command/")

    # _build_java_apis("com.thunder.livesdk.ThunderEngine", "../../apis")
    # _build_java_apis_from_java_file('/Users/yusong/Documents/yy/sdk-auto-test/ThunderEngine.java',
    #                                 "/Users/yusong/Documents/apis",
    #                                 sdk_version='2.9.15', package_name='com.thunder.livesdk.ThunderEngine')
    # _build_java_apis_from_file('../IBroadcastComponentApi.kt', "/Users/yyinc/PycharmProjects/buildertest/api/", sdk_version='2.9.15',
    #                                     package_name="tv.athena.live.api.broadcast")
    # path = os.path
    print(os.path.abspath(__file__))
    print(os.getcwd())
    ROOT_DIR = os.path.dirname(sys.modules['__main__'].__file__)
    print(sys.path)
